﻿using Onetube.Providers.Interfaces;
using Onetube.Providers.YoutubeDownloader;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Windows.Networking.BackgroundTransfer;

namespace Onetube.Providers
{
    public class YoutubeDownloadProvider : IYoutubeDownloadProvider
    {
        FileStorageProvider provider = null;

        public YoutubeDownloadProvider()
        {
            provider = new FileStorageProvider();
            this.Downloads = new System.Collections.ObjectModel.ObservableCollection<YoutubeDownloader.DownloadItem>();
            this.Downloads.CollectionChanged += Downloads_CollectionChanged;
        }

        void Downloads_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            try
            {
                Debug.WriteLine("Item Added");
                switch (e.Action)
                {
                    case System.Collections.Specialized.NotifyCollectionChangedAction.Add:

                        Debug.WriteLine("Item Added");
                        if (e.NewItems != null)
                        {
                            if (e.NewItems.Count > 0)
                            {
                                var item = (DownloadItem)e.NewItems[0];
                                item.OnDownloadCompleted += ItemOnDownloadCompleted;
                                item.OnDownloadFailed += ItemOnDownloadFailed;
                                item.OnDownloadProgressChanged += ItemOnDownloadProgressChanged;
                            }
                        }
                  
                        break;
                    case System.Collections.Specialized.NotifyCollectionChangedAction.Move:
                        break;
                    case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                   
                        Debug.WriteLine("Item Removed");
                        if (e.OldItems != null)
                        {
                            if (e.OldItems.Count > 0)
                            {
                                var item = (DownloadItem)e.OldItems[0];
                                item.OnDownloadCompleted -= ItemOnDownloadCompleted;
                                item.OnDownloadFailed -= ItemOnDownloadFailed;
                                item.OnDownloadProgressChanged -= ItemOnDownloadProgressChanged;
                            }
                        }
                        break;
                    case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
                        break;
                    case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                        Debug.WriteLine("Item Reset");
                        break;
                    default:
                        break;
                }
            }
            catch (Exception)
            {
            }
            if (MainCountDownloadChanged != null)
                MainCountDownloadChanged.Invoke(this, new EventArgsClasses.MainCountDownload(this.Downloads.Count));
        }

        async void ItemOnDownloadProgressChanged(object sender, EventArgsClasses.DownloadProgressChanged e)
        {
            try
            {
                var progress = await CalculateMainProgrees().ConfigureAwait(false);
                if (MainDownloadProgressChanged != null)
                    MainDownloadProgressChanged.Invoke(this, new EventArgsClasses.MainDownloadProgressEventArgs(progress));
            }
            catch (Exception)
            {
            }
        }

        void ItemOnDownloadFailed(object sender, EventArgsClasses.DownloadFailed e)
        {
            Debug.WriteLine("Download Failed");
            if (this.Downloads.Any(x => x.State == DownloadState.Downloading))
            {
                if (OnMainDownloadChanged != null)
                    OnMainDownloadChanged.Invoke(this, new EventArgsClasses.MainDownloadChanged(true));
            }
            else
            {
                if (OnMainDownloadChanged != null)
                    OnMainDownloadChanged.Invoke(this, new EventArgsClasses.MainDownloadChanged(false));
            }
        }

        async void ItemOnDownloadCompleted(object sender, EventArgsClasses.DownLoadCompleted e)
        {
            Debug.WriteLine("Download Completed");
            var item = sender as DownloadItem;
            if (this.Downloads.Contains(item))
            {
                try
                {
                    if (this.Downloads.Any(x => x.State == DownloadState.Downloading))
                    {
                        if (OnMainDownloadChanged != null)
                        {
                            OnMainDownloadChanged.Invoke(this, new EventArgsClasses.MainDownloadChanged(true));
                        }
                    }
                    else
                    {
                        if (OnMainDownloadChanged != null)
                            OnMainDownloadChanged.Invoke(this, new EventArgsClasses.MainDownloadChanged(false));
                    }
                    //   await provider.DeleteFileDownloadingAsync(item);
                    await provider.SaveFileAsync(new Entities.FileDownloadEntity
                    {
                        Url = item.Name,
                        ID = item.ID.ToString(),
                        MediaSize = item.MediaSize,
                        SmallImage = item.VideoDetails.Snippet.Thumbnails.Default.Url,
                        Type = (int)item.Type, VideoDetails = item.VideoDetails,
                        Extension = item.Extension
                    }).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                }
                this.Downloads.Remove(item);
            }
        }

        private System.Collections.ObjectModel.ObservableCollection<YoutubeDownloader.DownloadItem> downloads;

        public System.Collections.ObjectModel.ObservableCollection<YoutubeDownloader.DownloadItem> Downloads
        {
            get
            {
                return downloads;
            }
            set
            {
                downloads = value;
            }
        }

        public async Task<List<DownloadOperation>> GetSystemDownloads()
        {
            var activeDownloads = new List<DownloadOperation>();
            var downloads = await BackgroundDownloader.GetCurrentDownloadsForTransferGroupAsync(BackgroundTransferGroup.CreateGroup("OnetubeApp"));
            
            foreach (var item in downloads.ToList())
            {
                activeDownloads.Add(item);
            }
            return activeDownloads;
        }

        private async Task<int> CalculateMainProgrees()
        {
            try
            {
                var downloads = await GetSystemDownloads().ConfigureAwait(false);
                if (downloads != null)
                {
                    var totalBytesToDownload = downloads.Sum(x => (long)x.Progress.TotalBytesToReceive);
                    var totalBytesReceived = downloads.Sum(x => (long)x.Progress.BytesReceived);

                    return (int)((totalBytesReceived * 100) / totalBytesToDownload);
                }
            }
            catch (Exception)
            {
                throw;
            }
            return 0;
        }

        public event EventHandler<EventArgsClasses.MainDownloadProgressEventArgs> MainDownloadProgressChanged;

        System.Collections.ObjectModel.ObservableCollection<DownloadItem> IYoutubeDownloadProvider.Downloads
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public event EventHandler<EventArgsClasses.MainDownloadChanged> OnMainDownloadChanged;

        public event EventHandler<EventArgsClasses.MainCountDownload> MainCountDownloadChanged;
    }
}